#version 450 compatibility



layout(local_size_x = DEF_LocalSize, local_size_y = DEF_LocalSize, local_size_z = 1) in;

layout( binding = 0, rgba8ui) uniform uimage2D Pix;

layout( binding = 0 ) uniform Buf_LoalParameter0 {
    ivec4 m_Box;
    ivec2 m_Offset;
    uint m_PointNum;
    uint m_IntersectPointNum;
    uint m_Func;
    float m_LineWidth;
};

layout( binding = 1 ) uniform Buf_LoalParameter1 {
    uint m_Color;
};
layout(std430, binding = 2) buffer Buf_GlobalParameter2 {
    vec2 m_Lines[];
};


shared uint LineLen;
shared uint global_localID;
shared float HStep;
shared float VStep;
shared int LineWidthOffset;

shared vec2 lineDir;
shared vec2 tmpPosA;
shared vec2 tmpPosB;
shared uvec4 c;


void main(){
    const uint id = (gl_WorkGroupID.y * gl_NumWorkGroups.x) + gl_WorkGroupID.x;
    uint localID = gl_LocalInvocationIndex;

    if(localID == 0){
        uint endID = id+1;
        if(endID >= m_PointNum) return;
        
        tmpPosA = m_Lines[id + 1 ];
        tmpPosB = m_Lines[endID + 1];
        lineDir = (tmpPosB - tmpPosA);
        
        //LineLen = uint(abs(distance(tmpPosB, tmpPosA)));
        if(m_LineWidth>1){
            LineWidthOffset = int(round(m_LineWidth/2.0));
        } else {
            LineWidthOffset = 1;
        }
        
        
        //VStep = round(LineLen / ((lineDir.y / lineDir.x))) ;
        
        
        if(abs(lineDir.x) > abs(lineDir.y)){
            HStep =   (abs(lineDir.x) / abs(lineDir.y)) ;
            LineLen = uint(abs(distance(tmpPosB.x, tmpPosA.x)));
        }else{
            VStep =   (abs(lineDir.y) / abs(lineDir.x)) ;
            LineLen = uint(abs(distance(tmpPosB.y, tmpPosA.y)));
        }

        
        lineDir = normalize(lineDir);
        //HStep = abs(LineLen * lineDir.y) ;
        //VStep = abs(LineLen * lineDir.x) ;

        global_localID = 0;

        c = uvec4(bitfieldExtract(m_Color, 0, 8), 
                    bitfieldExtract(m_Color, 8, 8), 
                    bitfieldExtract(m_Color, 16, 8), 
                    bitfieldExtract(m_Color, 24, 8));
    }
    barrier();
    
    ivec2 coord = ivec2(0);
    vec2 TmpCoord;
    ivec2 OffsetCorrd = coord;
    for(int i=0; ; ){
        i = int(global_localID + localID);
        
        uvec4 AAC = c;
        if(i < LineLen){
            int X = i * int(sign(lineDir.x));
            int Y = i * int(sign(lineDir.y));

            

            //vec2 tc = lineDir * i;
            if(abs(lineDir.x) > abs(lineDir.y)) {
                coord.x = X;
                coord.y = Y/int(HStep+0.5);

                
            } else {
                int Step = (X)/int(VStep*0.5);
                coord.x = X/int(VStep);
                coord.y = Y;

                
            }
            
            coord.x += int(tmpPosA.x);
            coord.y += int(tmpPosA.y);
            //coord.x = int(tc.x);
            //coord.y = int(tc.y);
            coord.x += m_Offset.x;
            coord.y += m_Offset.y;
            
            
            imageStore(Pix, coord, c);
            
            if(abs(lineDir.x) >= abs(lineDir.y)) {
                OffsetCorrd = coord;
                for(float i=0; i<LineWidthOffset; i+=1){
                    imageStore(Pix, OffsetCorrd, c);
                    OffsetCorrd.y += 1;
                }
                OffsetCorrd = coord;
                for(float i=0; i<=LineWidthOffset; i+=1){
                    imageStore(Pix, OffsetCorrd, c);
                    OffsetCorrd.y -= 1;
                }
            } else {
                OffsetCorrd = coord;
                for(float i=0; i<LineWidthOffset; i+=1){
                    imageStore(Pix, OffsetCorrd, c);
                    OffsetCorrd.x += 1;
                }
                OffsetCorrd = coord;
                for(float i=0; i<=LineWidthOffset; i+=1){
                    imageStore(Pix, OffsetCorrd, c);
                    OffsetCorrd.x -= 1;
                }
            }
            
            

            
            uvec4 color = imageLoad(Pix, coord);
            OffsetCorrd = coord;
            if(abs(lineDir.x) >= abs(lineDir.y)) {
                
                
                OffsetCorrd.y += LineWidthOffset+1;
                color = imageLoad(Pix, OffsetCorrd);
                AAC.r = uint(float(color.r)*(1-lineDir.y) + float(c.r)*lineDir.y);
                AAC.g = uint(float(color.g)*(1-lineDir.y) + float(c.g)*lineDir.y);
                AAC.b = uint(float(color.b)*(1-lineDir.y) + float(c.b)*lineDir.y);

                imageStore(Pix, OffsetCorrd, AAC);

                OffsetCorrd.y -= LineWidthOffset+3;
                color = imageLoad(Pix, OffsetCorrd);
                AAC.r = uint(float(color.r)*(1-lineDir.y) + float(c.r)*lineDir.y);
                AAC.g = uint(float(color.g)*(1-lineDir.y) + float(c.g)*lineDir.y);
                AAC.b = uint(float(color.b)*(1-lineDir.y) + float(c.b)*lineDir.y);
                
                imageStore(Pix, OffsetCorrd, AAC);

            } else {
                OffsetCorrd.x += LineWidthOffset+1;
                color = imageLoad(Pix, OffsetCorrd);
                AAC.r = uint(float(color.r)*(1-lineDir.x) + float(c.r)*lineDir.x);
                AAC.g = uint(float(color.g)*(1-lineDir.x) + float(c.g)*lineDir.x);
                AAC.b = uint(float(color.b)*(1-lineDir.x) + float(c.b)*lineDir.x);
                
                imageStore(Pix, OffsetCorrd, AAC);

                OffsetCorrd.x -= LineWidthOffset+3;
                color = imageLoad(Pix, OffsetCorrd);
                AAC.r = uint(float(color.r)*(1-lineDir.x) + float(c.r)*lineDir.x);
                AAC.g = uint(float(color.g)*(1-lineDir.x) + float(c.g)*lineDir.x);
                AAC.b = uint(float(color.b)*(1-lineDir.x) + float(c.b)*lineDir.x);

                imageStore(Pix, OffsetCorrd, AAC);

            }

            
        }
        barrier();

        if(global_localID >= LineLen) break;
        if(localID == 0){
            global_localID += DEF_LocalSize*DEF_LocalSize;
        }
        barrier();
    }

}





